/**
 * WTF Engine
 *
 * License... etc.
 **
 * WTF Network Protocol
 **
 * Author: Sean Micklethwaite
 **/

#ifndef __net_protocolH__
#define __net_protocolH__

#include "interop.h"
#include <string.h>

namespace WtfEngine {
	VALUECLASS struct PacketData {
		static const unsigned int MAGIC = (((unsigned int)'W' << 24) + ((unsigned int)'T' << 16) + ((unsigned int)'F' << 8) + ((unsigned int)'1'));

		typedef enum {
			/// The type of the packet is MessagePacket
			PACKET_MESSAGE = 1,
			/// EventPacket - fires an event on the target
			PACKET_EVENT = 2,
			/// Contains game object update data
			PACKET_UPDATE = 3,
			/// Script command (requires privileged access)
			PACKET_PRIVILEGED_COMMAND = 4
		} tPacketType;

		/// Every packet must start with the MAGIC value defined above
		unsigned int	Magic;
		unsigned		PacketSize;
		tPacketType		PacketType;

		inline PacketData(tPacketType type, unsigned size): Magic(MAGIC), PacketSize(size), PacketType(type) {
		};

		inline bool isValidPacket() const {
			return (Magic == MAGIC);
		};
	};

	VALUECLASS struct MessagePacket : public PacketData {
		typedef enum {
			/// The acknowledge message is sent after a message which needs acknowledgement, to
			/// confirm that it has been recieved
			MSG_ACK = 1,

			/// Broadcasting to find a party for a game - the initial stage
			/// in matchmaking
			MSG_PARTY_BROADCAST,

			/// Attempting to initiate connection
			MSG_CONNECT,
			/// Accepting a connection, returning our details
			MSG_HANDSHAKE,

			/// Request privlileged access
			MSG_REQUEST_PRIVILEGED_ACCESS
		} tMessageType;

		tMessageType	MessageType;

		inline MessagePacket(tMessageType type, unsigned uSize): PacketData(PACKET_MESSAGE, uSize),
			MessageType(type) {
		};
	};

	VALUECLASS struct PartyBroadcastMessage : public MessagePacket {
		unsigned uCurrentPartySize, uRequestedPartySize;
		/// A special value indicating which game is being played
		unsigned uGameId;
		/// A value identifying the type of game searched for
		int      iGameType;

		unsigned short wPort;

		inline PartyBroadcastMessage(unsigned uSize = sizeof(PartyBroadcastMessage))
		: MessagePacket(MSG_PARTY_BROADCAST, uSize) {
		};
	};

	VALUECLASS struct CommandPacket : public PacketData {
		typedef enum {
			CMD_SCRIPT = 1
		} tCommand;

		tCommand	Command;

		inline CommandPacket(tCommand cmd, unsigned uSize)
			: PacketData(PACKET_PRIVILEGED_COMMAND, sizeof(CommandPacket) + uSize),
			  Command(cmd)
		{ };
	};

	template <unsigned Len>
	VALUECLASS struct ScriptCommandPacket : public CommandPacket {
		char Script[Len];

		inline ScriptCommandPacket(const char * pScript): CommandPacket(CMD_SCRIPT, Len) {
			memcpy(Script, pScript, Len);
		};
	};
};

#endif
